// 导入Game_Controller脚本
import GC from "./Game_Controller";

// 状态
// 左走 右走 跳跃 攻击 静止 受伤 死亡
const enum State{
    left, right, atttack, idle, injured, death,
};

const {ccclass, property} = cc._decorator;

@ccclass
export default class Foe extends cc.Component {

    // Game_Controller脚本所在节点
    GC: GC = null;


    @property({displayName: "敌人", tooltip: "敌人，其实就是自己", type: sp.Skeleton})
    foe: sp.Skeleton = null;


    // 橙色字体，在Game_Controller脚本上获取
    orange_typeface: cc.Font = null;

    // 伤害字体，在Game_Controller脚本上获取
    damage_typeface: cc.Font = null;




    // @property({displayName: "玩家", tooltip: "玩家", type: cc.Node})
    player: cc.Node = null;

    @property({displayName: "左攻击范围", tooltip: "左攻击范围", type: cc.Node})
    attack_left: cc.Node = null;

    @property({displayName: "显示血条的精灵", tooltip: "显示血条的精灵", type: cc.Sprite})
    HP_sp: cc.Sprite = null;

    @property({displayName: "右攻击范围", tooltip: "右攻击范围", type: cc.Node})
    attack_right: cc.Node = null;


    @property({displayName: "行走动画名称", tooltip: "行走动画名称"})
    walk_anim_name: string = "";

    @property({displayName: "技能动画名称", tooltip: "技能动画名称"})
    skill_name: string = "";


    @property({displayName: "行走速度", tooltip: "行走速度", type: cc.Float})
    walk_speed: number = 80;

    @property({displayName: "怪物走到哪里时停下攻击人物", tooltip: "怪物走到距离人物哪里时停下攻击人物", type: cc.Float})
    dis: number = 80;



    @property({displayName: "满的血量", tooltip: "满的血量", type: cc.Float})
    HP_full: number = 200;

    @property({displayName: "当前血量", tooltip: "当前血量", type: cc.Float})
    HP_cur: number = 200;

    @property({displayName: "普攻攻击力", tooltip: "普攻攻击力", type: cc.Float})
    ATK_num: number = 20;

    @property({displayName: "技能攻击力", tooltip: "技能攻击力，只有BOSS生效", type: cc.Float})
    Skill_num: number = 80;



    @property({displayName: "是否是Boss", tooltip: "是否是Boss"})
    is_boss: boolean = false;


    // 最终输出结果
    ATK_num_F: number = 20;

    // 开始时状态是静止
    state = State.idle;

    // 是否可以攻击
    is_attack_OK: boolean = false;

    // 是否可以攻击
    is_atk: boolean = true;
    // 是否可以使用技能
    is_skill: boolean = false

    // 是否可以死
    is_death_OK: boolean = true;

    // 是否是第一次落地
    is_groud_first: boolean = true;

    // 是否开始变淡
    is_thin: boolean = false;

    // 是否播放完死亡动画
    is_death_anim: boolean = false;

    onLoad () {
        // 获取Game_Controller脚本
        this.GC = cc.find("Canvas").getComponent("Game_Controller");

        // 左右攻击范围全部隐藏
        this.attack_left.active = false;
        this.attack_right.active = false;

        // 当前血量为满的血量
        this.HP_cur = this.HP_full;


        // 为了防止所有怪物重叠在一起   加上随机数
        this.dis += this.randomNumber(-30, 30);
    }

    start () {
        // 获取橙色字体
        this.orange_typeface = cc.find("Canvas").getComponent("Game_Controller").orange_typeface;
        // 获取主角
        this.player = cc.find("Canvas/player");

        // 获取伤害字体
        this.damage_typeface = cc.find("Canvas").getComponent("Game_Controller").damage_typeface;
    }

    update (dt: number) {
        // 每帧更新血条
        this.HP_sp.fillRange = this.HP_cur / this.HP_full;
        // 根据怪物朝向修改血条朝向
        if (this.foe.node.scaleX > 0) {
            this.HP_sp.node.scaleX = 1;
        } else if (this.foe.node.scaleX < 0) {
            this.HP_sp.node.scaleX = -1;
        }


        // 如果怪物的透明度小于等于0
        if (this.foe.node.opacity <= 0) {
            // 怪物销毁
            this.node.destroy();
            // 打印log
            cc.log(this.foe.node.name + "怪物已经销毁");
        }
        

        
        // 如果状态为静止
        if (this.state == State.idle) {
            // 打印log
            // cc.log("状态： 静止");

            // 如果动画不为静止
            if (this.foe.animation != "stand") {
                // 动画为静止
                this.foe.animation = "stand";
            }
            // 角色刚体线性速度X为0
            this.foe.getComponent(cc.RigidBody).linearVelocity = cc.v2(0, this.foe.getComponent(cc.RigidBody).linearVelocity.y);
            // cc.log("静止状态");
        }
        // 如果状态为受伤
        else if (this.state == State.injured && this.is_death_anim == false) {
            // 不可以攻击
            this.is_attack_OK = false;

            let self = this;

            // 如果动画不为受伤
            if (this.foe.animation != "injured") {
                // 动画为受伤
                this.foe.animation = "injured";
            }

            // 当动画播放完时
            this.foe.setCompleteListener(function () {
                // 如果状态为受伤
                if (self.state == State.injured) {
                    // 状态为静止
                    self.state = State.idle;
                    // 清空管道
                    self.foe.clearTracks();
                    // 可以攻击
                    self.is_attack_OK = true;
                }
            });
            // 打印log
            cc.log("怪物受伤了");
        }
        // 如果状态为左走 
        else if (this.state == State.left) {
            // 打印log
            // cc.log("状态： 左走");

            // 如果动画不为走路
            if (this.foe.animation != this.walk_anim_name) {
                // 动画为走路
                this.foe.animation = this.walk_anim_name;
            }
            // 根据移动速度来移动怪物
            this.foe.node.x -= this.walk_speed * dt;
            // 缩放
            this.foe.node.scaleX = -0.6;
        }
        // 如果状态为右走 
        else if (this.state == State.right) {
            // 打印log
            // cc.log("状态： 右走");

            // 如果动画不为走路
            if (this.foe.animation != this.walk_anim_name) {
                // 动画为走路
                this.foe.animation = this.walk_anim_name;
            }
            // 根据行走速度移动怪物
            this.foe.node.x += this.walk_speed * dt;
            // 缩放
            this.foe.node.scaleX = 0.6;
        } 
        // 如果状态为右走 
        else if (this.state == State.atttack) {

            // 如果不为Boss
            if (this.is_boss == false) {
                // 最终攻击力为普攻攻击力
                this.ATK_num_F = this.ATK_num;
                // 如果动画不为攻击
                if (this.foe.animation != "attack") {
                    // 动画为攻击
                    this.foe.animation = "attack";
                }

                let self = this;

                // 当动画播放完时
                this.foe.setCompleteListener(function () {
                    // 如果状态为攻击
                    if (self.state == State.atttack) {
                        // 打开攻击范围，0.2秒后关闭攻击范围
                        self.open_attack(0.2);
                    }
                });
            // cc.log("怪物攻击了！");


            }
            // 如果是Boss 
            else {     
                // 如果可以攻击   
                if (this.is_atk == true) {
                    // 攻击
                    this.ATK();
                }
                // 如果可以使用技能
                if (this.is_skill == true) {
                    // 使用技能
                    this.skill();
                }
            }


        } 
        // 如果状态为死亡 
        else if (this.state == State.death) {
            // 不可以攻击
            this.is_attack_OK = false;

            // 动画不循环播放
            this.foe.loop = false;
         
            // 开始变淡
            this.is_thin = true;

            // 如果动画不为死亡并且可以播放动画
            if (this.foe.animation != "death" && this.is_death_anim == false) {
                // 动画为死亡
                this.foe.animation = "death";
                
                // 播放完死亡动画
                this.is_death_anim = true;
                // 打印log
                cc.log("开始播放死亡动画。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");
            }

            // let self = this;

            /* // 在播放完成后
            this.foe.setCompleteListener(function () {
                // 动画为空
                self.foe.animation = "";
                // 不循环播放
                self.foe.loop = false;

                cc.log("死亡动画播放完了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

                // 播放完死亡动画了
                self.is_death_anim = true;
            }); */


            // 打印log
            cc.log("状态为死亡");
        }  


        // 如果开始变淡
        if (this.is_thin == true) {
            let self = this;

            // 减少透明度
            this.foe.node.opacity -= 1;
            // 如果播放完了死亡动画
            if (this.is_death_anim == true) {
                // 不循环播放动画
                this.foe.loop = false;
                // 定时器，规定时间后动画为空
                /* this.scheduleOnce(function () {
                    self.foe.animation = "";
                }, 1); */

                
                // 动画播放完成后
                this.foe.setCompleteListener(function () {
                    // 定时器 0.3秒后动画为空
                    self.scheduleOnce(function () {
                        // 动画为空
                        self.foe.animation = "";
                    }, 0.3);
                });
            }

        }



        // 如果没血了并可以死亡，死亡
        if (this.HP_cur <= 0 && this.is_death_OK == true) {
            // 封装好的死亡函数
            this.death();
            // 不可以死亡了
            this.is_death_OK = false;

            // 以下代码不执行
            return;
        }



        // 如果可以攻击
        if (this.is_attack_OK == true) {
            // 怪物X减去主角X
            let dis = this.foe.node.x - this.player.x;
            // 如果在右侧
            if (dis > this.dis) {
                // 状态为左走
                this.state = State.left;
            }
            // 如果在左侧 
            else if (dis < -this.dis) {
                // 状态为右走
                this.state = State.right;
            } 
            // 如果上面两种都不是
            else {
                // 状态为攻击
                this.state = State.atttack;
            }
        }        



    }


    // 碰撞回调
    onBeginContact (contact/*碰撞*/:cc.PhysicsContact,selfCollider/*被碰撞*/:cc.PhysicsCollider,otherConllider/*另一个碰撞体*/:cc.PhysicsCollider): void {
        // console.log("onBeginContact");
        // 如果是第一次碰到地
        if (this.is_groud_first == true) {
            // 不是第一次碰到地
            this.is_groud_first = false;
            // 可以攻击
            this.is_attack_OK = true;
        }
        //只在两个碰撞体开始接触时调用一次
    }



    // 打开攻击范围专用函数，num为几秒恢复
    open_attack (num: number) {
        let self = this;
        // 开启左右攻击范围
        this.attack_left.active = true;
        this.attack_right.active = true;
        // 在num秒后关闭左右攻击范围
        this.scheduleOnce(function () {
            self.attack_left.active = false;
            self.attack_right.active = false;
        }, num);
    }



    // 减少生命值专用函数，num为减少多少生命值
    reduce_HP (num: number) {
        // 减少
        this.HP_cur -= num;
    }



    // 碰撞回调
    onCollisionEnter(other, self){// 当碰撞产生的时候调用   other 产生碰撞的另一个碰撞组件self  产生碰撞的自身的碰撞组件
        // 如果是角色的攻击范围
        if (other.node.group == "player_attack") {
            // 随机数
            let r = Math.random() * 100;

            // 获取Player脚本
            let player = other.node.parent.getComponent("Player");
            
            // 如果角色暴击了
            if (r <= player.CRI) {
                // 打印log
                cc.log("暴击并打到了敌人，敌人名称" + this.node.name);
                // 状态为受伤
                this.state = State.injured;
                // 无敌0.21秒
                this.invincible(0.21);

                // 获取Player脚本
                let player = other.node.parent.getComponent("Player");
                // 创建新的暴击文字
                this.new_num_CRI(player.ATK * 2)
                // 减少生命值
                this.reduce_HP(player.ATK * 2);
            }
            // 如果没有暴击 
            else {
                // 打印log
                cc.log("打到了敌人，敌人名称" + this.node.name);
                // 状态为受伤
                this.state = State.injured;
                // 无敌0.21秒
                this.invincible(0.21);

                // 获取Player脚本
                let player = other.node.parent.getComponent("Player");
                // 创建新的文字
                this.new_num(player.ATK)
                // 减少生命值
                this.reduce_HP(player.ATK);
            }
        }

        // 如果是角色的技能
        if (other.node.group == "skill_ATK") {
            // 打印log
            cc.log("技能打到了敌人，敌人名称" + this.node.name);
            // 状态为受伤
            this.state = State.injured;
            // 无敌0.21秒
            this.invincible(0.21);

            // 获取角色技能攻击力
            let ATK = other.node.parent.getComponent("Skill_ATK");
            // 创建新的文字
            this.new_num(ATK.ATK)
            // 减少生命值
            this.reduce_HP(ATK.ATK);
        }

        // 如果是角色的击退技能
        if (other.node.group == "repel") {
            // 无敌0.21秒
            this.invincible(0.21);
            // 击退
            this.repel();
            // 打印log
            cc.log("击退技能已经达到敌人");
        }
    }


    // 无敌函数，num为几秒后恢复
    invincible (num: number) {
        // 将分组设为默认
        this.node.group = "default";
        let self = this;
        // num秒后恢复分组
        this.scheduleOnce(function () {
            self.node.group = "foe";
        }, num);
    }


    // 死亡函数
    death () {
        // 状态为death
        this.state = State.death;

        // 随机数
        let num = Math.random() * 100;

        // 如果可以掉落物品
        if (num <= this.GC.drop_probability) {
            // 掉落物品
            this.GC.create_new_drop_0(cc.v2(this.node.x, this.node.y + 20));
        }

        // 如果是Boss
        if (this.is_boss == true) {
            // 过关
            this.GC.pass();
            // 掉落武器
            this.GC.create_new_drop_weapon(cc.v2(this.node.x, this.node.y + 20), this.GC.map_num);


            // 获取任务BOSS击杀数据
            let boss = cc.sys.localStorage.getItem("Task_Boss");
            // 如果为空
            if (boss == null) {
                // 存储
                cc.sys.localStorage.setItem("Task_Boss", 1);
            } else {
                // 如果不为空
                // 加上1
                let n = Number(boss) + 1;
                // 存储
                cc.sys.localStorage.setItem("Task_Boss", n);
            }
        } 
        // 如果为小兵
        else {
            // 获取任务小怪击杀数据
            let foe = cc.sys.localStorage.getItem("Task_Foe");
            // 如果为空
            if (foe == null) {
                // 存储
                cc.sys.localStorage.setItem("Task_Foe", 1);
            } else {
                // 如果不为空
                // 加上1
                let n = Number(foe) + 1;
                // 存储
                cc.sys.localStorage.setItem("Task_Foe", n);
            }
        }



        // 经验值为随机
        let add_EXP_num = this.randomNumber(this.GC.add_EXP_num[this.GC.map_num - 1].x, this.GC.add_EXP_num[this.GC.map_num - 1].y);
        // 增加经验值
        this.player.getComponent("Player").add_EXP(add_EXP_num);

        // 如果是Boss
        if (this.is_boss == true) {
            // 加金币
            this.GC.add_money(this.GC.add_money_num[this.GC.map_num - 1].y);
        } else {
            // 加金币
            this.GC.add_money(this.GC.add_money_num[this.GC.map_num - 1].x);
        }
    }

    

    // 创建新的伤害数字专用函数，num为数字的值
    new_num (num: number) {
        // 新的节点
        let node = new cc.Node;
        // 添加label组件
        node.addComponent(cc.Label);

        // 获取label组件
        let lb = node.getComponent(cc.Label);
        // 显示的内容为取证后的num
        lb.string = Math.floor(num).toString();
        // 字体为橙色
        lb.font = this.orange_typeface;

        // 父节点为canvas
        node.parent = cc.find("Canvas");
        // X为怪物X
        node.x = this.foe.node.x;
        // Y在怪物Y上方
        node.y = this.foe.node.y + (this.foe.node.height / 2) + 30;


        // 移动动作
        let move = cc.moveBy(2, cc.v2(0, 100));
        // 回调函数
        let func = cc.callFunc(function () {
            // 销毁
            node.destroy();
        }, this);
        // 两个结合在一起
        let action = cc.sequence(move, func);
        // 执行动作
        node.runAction(action);
    }


    //  暴击后   创建新的伤害数字函数，num为数字的值
    new_num_CRI (num: number) {
        // 创建新的节点
        let node = new cc.Node;
        // 添加label组件
        node.addComponent(cc.Label);

        // 获取label组件
        let lb = node.getComponent(cc.Label);
        // 显示的内容为取整的num
        lb.string = Math.floor(num).toString();
        // 字体为伤害字体
        lb.font = this.damage_typeface;

        // 父节点为canvas
        node.parent = cc.find("Canvas");
        // X为怪物X
        node.x = this.foe.node.x;
        // Y为怪物Y上方
        node.y = this.foe.node.y + (this.foe.node.height / 2) + 30;


        // 移动动作
        let move = cc.moveBy(2, cc.v2(0, 100));
        // 回调函数
        let func = cc.callFunc(function () {
            node.destroy();
        }, this);
        // 两个结合在一起
        let action = cc.sequence(move, func);
        // 执行动作
        node.runAction(action);
    }


    // 击退专用函数
    repel () {
        // 如果怪物冲着右边
        if (this.foe.node.scaleX > 0) {
            // 移动动作
            let ac = cc.moveBy(0.5, cc.v2(-150, 0));
            // 执行
            this.foe.node.runAction(ac);
        } 
        // 如果怪物冲着左边
        else {
            // 移动动作
            let ac = cc.moveBy(0.5, cc.v2(150, 0));
            // 执行
            this.foe.node.runAction(ac);
        }
    }



    // BOSS攻击专用函数
    ATK () {
        // 最终攻击力为普攻攻击力
        this.ATK_num_F = this.ATK_num;
        // 如果动画不为攻击
        if (this.foe.animation != "attack") {
            // 动画为攻击
            this.foe.animation = "attack";
        }

        let self = this;

        // 当动画播放完后
        this.foe.setCompleteListener(function () {
            // 如果状态为攻击
            if (self.state == State.atttack) {
                // 打开攻击范围 0.2秒后恢复
                self.open_attack(0.2);
                // 0.2秒后不可以攻击，可以使用技能
                self.scheduleOnce(function () {
                    self.is_atk = false;
                    self.is_skill = true;
                }, 0.2);
            }
        });
    }


    // BOSS用技能专用函数
    skill () {
        // 最终攻击力为技能攻击力
        this.ATK_num_F = this.Skill_num;
        // 如果动画不为技能动画
        if (this.foe.animation != this.skill_name) {
            // 动画为技能动画
            this.foe.animation = this.skill_name;
        }

        let self = this;

        // 当动画播放完后
        this.foe.setCompleteListener(function () {
            // 如果状态为攻击
            if (self.state == State.atttack) {
                // 打开攻击范围
                self.open_attack(0.2);
                // 0.2秒后不可以使用技能，可以普攻
                self.scheduleOnce(function () {
                    self.is_atk = true;
                    self.is_skill = false;
                }, 0.2);
            }
        });
    }

    // 随机数
    randomNumber(min : number, max : number): number{
        return Math.round(Math.random() * (min - max) + max);
    }


}
